package kv

import (
	"database/sql"
	"gitee.com/tziye/renai-go/common"
	"gitee.com/tziye/renai-go/renai"
	"gitee.com/tziye/renai-go/sqlproxy"
)

type PairOperator struct {
	RenaiClient *renai.RenaiClient
	Db          *sql.DB
}

func NewPairOperator(renaiClient *renai.RenaiClient) *PairOperator {
	return &PairOperator{
		RenaiClient: renaiClient,
		Db:          renaiClient.Db,
	}
}

func (pairOperator *PairOperator) Key(key string) RenaiKey {
	return queryKey(pairOperator.Db, key, Pair)
}

func (pairOperator *PairOperator) Keys(keys []string) []RenaiKey {
	return queryKeys(pairOperator.Db, keys, Pair)
}

func (pairOperator *PairOperator) AllKeys() []RenaiKey {
	return keysByType(pairOperator.Db, Pair)
}

func (pairOperator *PairOperator) Like(pattern string) []RenaiKey {
	return keysLike(pairOperator.Db, pattern, Pair)
}

func (pairOperator *PairOperator) Regexp(pattern string) []RenaiKey {
	return keysRegexp(pairOperator.Db, pattern, Pair)
}

func (pairOperator *PairOperator) Total() int {
	return total(pairOperator.Db, Pair)
}

func (pairOperator *PairOperator) Expire(key string, expireSeconds int) {
	expire(pairOperator.Db, key, expireSeconds, Pair)
}

func (pairOperator *PairOperator) Exists(key string) bool {
	return exists(pairOperator.Db, key, Pair)
}

func (pairOperator *PairOperator) Delete(key string) {
	delete(pairOperator.Db, key, Pair)
}

func (pairOperator *PairOperator) BatchDelete(keys []string) {
	batchDelete(pairOperator.Db, keys, Pair)
}

func (pairOperator *PairOperator) Flush() {
	flush(pairOperator.Db, Pair)
}

func (pairOperator *PairOperator) Set(key string, value any) {
	s := `INSERT INTO renai_kv_pair(k, v) VALUES (?, ?) ON DUPLICATE KEY UPDATE v = VALUES(v), 
          	expire_time = IF(expire_time <= NOW(), NULL, expire_time), update_time = NOW()`
	sqlproxy.Exec(pairOperator.Db, s, key, common.String(value))
}

func (pairOperator *PairOperator) SetExpire(key string, value any, expireSeconds int) {
	s := `INSERT INTO renai_kv_pair(k, v, expire_time) VALUES (?, ?, DATE_ADD(NOW(), INTERVAL ? SECOND))
          	ON DUPLICATE KEY UPDATE v = VALUES(v), expire_time = VALUES(expire_time), update_time = NOW()`
	sqlproxy.Exec(pairOperator.Db, s, key, common.String(value), expireSeconds)
}

func (pairOperator *PairOperator) Get(key string) string {
	s := "SELECT v FROM renai_kv_pair_valid WHERE k = ?"
	row := sqlproxy.QueryRow(pairOperator.Db, s, key)
	var value sql.NullString
	err := row.Scan(&value)
	common.LogErr(err)
	return value.String
}

func (pairOperator *PairOperator) Incr(key string, num int64) int64 {
	row := sqlproxy.CallRow(pairOperator.Db, common.KV_PAIR_INCR, key, num)
	var value sql.NullInt64
	err := row.Scan(&value)
	common.PanicErr(err)
	return value.Int64
}
